#include "auto_door_manager.h"

namespace application {
namespace auto_door {

namespace {
QString sanitizePoint(const QString& point) {
    return point.trimmed().toUpper();
}
} // namespace

QString AutoDoorManager::buildPairKey(const QString& from, const QString& to) {
    return QStringLiteral("%1->%2").arg(sanitizePoint(from), sanitizePoint(to));
}

// ========== 构造与析构 ==========

AutoDoorManager::AutoDoorManager(int floor, std::shared_ptr<kernel::ILogger> logger, QObject* parent)
    : QObject(parent)
    , m_floor(floor)
    , m_logger(logger)
{
    // 创建心跳超时检测定时器
    m_timeoutTimer = new QTimer(this);
    connect(m_timeoutTimer, &QTimer::timeout, this, &AutoDoorManager::checkDeviceTimeout);
    m_timeoutTimer->start(10000);  // 每10秒检查一次
}

AutoDoorManager::~AutoDoorManager()
{
    stopConnection();
}

QString AutoDoorManager::floorTag() const
{
    return m_floor >= 0 ? QString::number(m_floor) : QStringLiteral("global");
}

// ========== TCP Server 管理 ==========

bool AutoDoorManager::initConnection(quint16 port)
{
    if (m_tcpServer) {
        if (m_serverPort == port) {
            if (m_logger) {
                m_logger->warning(QString("TCP Server already running on port %1").arg(m_serverPort));
            }
            return true;
        }
        stopConnection();
    }

    m_serverPort = port;
    m_tcpServer = new infrastructure::io::TcpSocketServer(20, this);  // 最多20个连接

    if (!m_tcpServer->listen(QHostAddress::Any, port)) {
        if (m_logger) {
            m_logger->error(QString("自动门TCP服务器启动失败: 端口=%1, 错误=%2")
                .arg(port)
                .arg(m_tcpServer->errorString()));
        }
        delete m_tcpServer;
        m_tcpServer = nullptr;
        return false;
    }

    // 连接信号
    connect(m_tcpServer, &infrastructure::io::TcpSocketServer::sig_connectClient,
            this, &AutoDoorManager::onNewConnection);
    connect(m_tcpServer, &infrastructure::io::TcpSocketServer::sig_sockDisConnect,
            this, &AutoDoorManager::onClientDisconnected);

    if (m_logger) {
        m_logger->info(QString("自动门TCP服务器启动: 范围=%1, 端口=%2").arg(floorTag()).arg(port));
    }

    return true;
}

void AutoDoorManager::stopConnection()
{
    if (!m_tcpServer) {
        return;
    }

    // 清理所有设备连接
    for (auto& device : m_devices) {
        if (device.readConnection) {
            QObject::disconnect(device.readConnection);
        }
        if (device.protocol) {
            device.protocol->deleteLater();
            device.protocol = nullptr;
        }
        // TcpSocketClient 由 TcpSocketServer 管理，不需要手动删除
    }

    m_devices.clear();
    m_socketToDevice.clear();

    for (auto& pending : m_pendingDevices) {
        if (pending.readConnection) {
            QObject::disconnect(pending.readConnection);
        }
        if (pending.protocol) {
            pending.protocol->deleteLater();
            pending.protocol = nullptr;
        }
    }
    m_pendingDevices.clear();
    m_protocolToSocket.clear();
    m_programToDoor.clear();

    m_tcpServer->close();
    delete m_tcpServer;
    m_tcpServer = nullptr;

    if (m_logger) {
        m_logger->info(QString("自动门TCP服务器已停止: 范围=%1").arg(floorTag()));
    }
}

// ========== 自动门管理 ==========

void AutoDoorManager::addDoor(int doorId, quint32 deviceId, const QString& point1, const QString& point2,
                               quint8 openMask, quint8 closeMask, int floor)
{
    if (m_doorConfigs.contains(doorId)) {
        if (m_logger) {
            m_logger->warning(QString("门ID %1 已存在").arg(doorId));
        }
        return;
    }

    // 创建门配置
    DoorConfig config;
    config.doorId = doorId;
    config.floor = floor;
    config.deviceId = deviceId;
    config.point1 = point1;
    config.point2 = point2;
    config.openMask = openMask & 0x07;  // 只保留低3位
    config.closeMask = closeMask & 0x07;
    config.doorObject = std::make_shared<AutoDoor>(doorId, point1, point2, m_logger);

    m_doorConfigs.insert(doorId, config);

    // 建立 deviceId -> doorId 映射
    m_deviceToDoor.insert(deviceId, doorId);

    // 建立点位映射
    if (!point1.isEmpty()) {
        m_pointToDoor.insert(point1, doorId);
    }
    if (!point2.isEmpty()) {
        m_pointToDoor.insert(point2, doorId);
    }

    // 建立路径映射（双向）
    if (!point1.isEmpty() && !point2.isEmpty()) {
        m_segmentToDoor.insert(buildPairKey(point1, point2), doorId);
        m_segmentToDoor.insert(buildPairKey(point2, point1), doorId);
    }

    // 连接信号
    connect(config.doorObject.get(), &AutoDoor::stateChanged, this, [this, doorId](DoorState state) {
        emit doorStateChanged(doorId, state);
    });

    if (m_logger) {
        m_logger->debug(QString("范围 %1 添加自动门: ID=%2, DeviceID=0x%3, 点1=%4, 点2=%5, 开门掩码=0x%6, 关门掩码=0x%7")
            .arg(floorTag())
            .arg(doorId)
            .arg(deviceId, 8, 16, QChar('0'))
            .arg(point1)
            .arg(point2)
            .arg(openMask, 2, 16, QChar('0'))
            .arg(closeMask, 2, 16, QChar('0')));
    }

    emit doorAdded(doorId);
}

QList<AutoDoorManager::DoorInfo> AutoDoorManager::getDoorInfos() const
{
    QList<DoorInfo> infos;
    infos.reserve(m_doorConfigs.size());

    for (auto it = m_doorConfigs.constBegin(); it != m_doorConfigs.constEnd(); ++it) {
        const DoorConfig& config = it.value();
        DoorInfo info;
        info.doorId = config.doorId;
        info.floor = (config.floor >= 0) ? config.floor : m_floor;
        info.deviceId = config.deviceId;
        info.point1 = config.point1;
        info.point2 = config.point2;
        if (config.doorObject) {
            info.state = config.doorObject->getState();
        }
        info.deviceOnline = isDeviceOnline(config.deviceId);
        infos.append(info);
    }

    return infos;
}

void AutoDoorManager::removeDoor(int doorId)
{
    if (!m_doorConfigs.contains(doorId)) {
        return;
    }

    const DoorConfig& config = m_doorConfigs[doorId];

    // 移除 deviceId 映射
    m_deviceToDoor.remove(config.deviceId);

    // 移除点位映射
    m_pointToDoor.remove(config.point1);
    m_pointToDoor.remove(config.point2);

    // 移除路径映射
    if (!config.point1.isEmpty() && !config.point2.isEmpty()) {
        m_segmentToDoor.remove(buildPairKey(config.point1, config.point2));
        m_segmentToDoor.remove(buildPairKey(config.point2, config.point1));
    }

    m_doorConfigs.remove(doorId);
    if (QTimer* timer = m_autoCloseTimers.take(doorId)) {
        timer->stop();
        timer->deleteLater();
    }

    if (m_logger) {
        m_logger->debug(QString("移除自动门: ID=%1").arg(doorId));
    }

    emit doorRemoved(doorId);
}

std::shared_ptr<AutoDoor> AutoDoorManager::getDoor(int doorId) const
{
    if (m_doorConfigs.contains(doorId)) {
        return m_doorConfigs[doorId].doorObject;
    }
    return nullptr;
}

QList<int> AutoDoorManager::getAllDoorIds() const
{
    return m_doorConfigs.keys();
}

std::shared_ptr<AutoDoor> AutoDoorManager::findDoorByPoint(const QString& pointName) const
{
    if (m_pointToDoor.contains(pointName)) {
        int doorId = m_pointToDoor[pointName];
        return getDoor(doorId);
    }
    return nullptr;
}

std::shared_ptr<AutoDoor> AutoDoorManager::findDoorBySegment(const QString& from, const QString& to) const
{
    if (from.isEmpty() || to.isEmpty()) {
        return nullptr;
    }

    const QString key = buildPairKey(from, to);
    auto it = m_segmentToDoor.constFind(key);
    if (it == m_segmentToDoor.constEnd()) {
        return nullptr;
    }
    return getDoor(it.value());
}

// ========== 控制接口 ==========

void AutoDoorManager::openDoor(int doorId)
{
    if (!m_doorConfigs.contains(doorId)) {
        if (m_logger) {
            m_logger->warning(QString("门ID %1 不存在").arg(doorId));
        }
        return;
    }

    const DoorConfig& config = m_doorConfigs[doorId];

    // 检查设备是否在线
    if (!isDeviceOnline(config.deviceId)) {
        if (m_logger) {
            m_logger->warning(QString("门 %1 的设备 0x%2 离线，无法控制")
                .arg(doorId)
                .arg(config.deviceId, 8, 16, QChar('0')));
        }
        return;
    }

    // 生成 ProgramID
    uint32_t programId = generateProgramId();
    m_programToDoor.insert(programId, doorId);

    // 发送LED控制指令（开门）
    if (sendLedControl(config.deviceId, programId, config.openMask)) {
        if (m_logger) {
            m_logger->debug(QString("发送开门指令: 门=%1, DeviceID=0x%2, ProgramID=0x%3, Mask=0x%4")
                .arg(doorId)
                .arg(config.deviceId, 8, 16, QChar('0'))
                .arg(programId, 8, 16, QChar('0'))
                .arg(config.openMask, 2, 16, QChar('0')));
        }
        startOrResetAutoCloseTimer(doorId);
    }
}

void AutoDoorManager::closeDoor(int doorId)
{
    if (!m_doorConfigs.contains(doorId)) {
        if (m_logger) {
            m_logger->warning(QString("门ID %1 不存在").arg(doorId));
        }
        return;
    }

    const DoorConfig& config = m_doorConfigs[doorId];

    // 检查设备是否在线
    if (!isDeviceOnline(config.deviceId)) {
        if (m_logger) {
            m_logger->warning(QString("门 %1 的设备 0x%2 离线，无法控制")
                .arg(doorId)
                .arg(config.deviceId, 8, 16, QChar('0')));
        }
        return;
    }

    // 生成 ProgramID
    uint32_t programId = generateProgramId();
    m_programToDoor.insert(programId, doorId);

    // 发送LED控制指令（关门）
    if (sendLedControl(config.deviceId, programId, config.closeMask)) {
        if (m_logger) {
            m_logger->info(QString("发送关门指令: 门=%1, DeviceID=0x%2, ProgramID=0x%3, Mask=0x%4")
                .arg(doorId)
                .arg(config.deviceId, 8, 16, QChar('0'))
                .arg(programId, 8, 16, QChar('0'))
                .arg(config.closeMask, 2, 16, QChar('0')));
        }
        stopAutoCloseTimer(doorId);
    }
}

// ========== 设备管理 ==========

bool AutoDoorManager::isDeviceOnline(quint32 deviceId) const
{
    if (m_devices.contains(deviceId)) {
        return m_devices[deviceId].state == DeviceState::Online;
    }
    return false;
}

QList<quint32> AutoDoorManager::getOnlineDevices() const
{
    QList<quint32> onlineDevices;
    for (auto it = m_devices.constBegin(); it != m_devices.constEnd(); ++it) {
        if (it.value().state == DeviceState::Online) {
            onlineDevices.append(it.key());
        }
    }
    return onlineDevices;
}

// ========== TCP连接处理（槽函数） ==========

void AutoDoorManager::onNewConnection(qint64 socketDescriptor, const QString& ip, quint16 port)
{
    if (!m_tcpServer) {
        return;
    }

    auto clients = m_tcpServer->getClients();
    if (!clients.contains(socketDescriptor)) {
        if (m_logger) {
            m_logger->error(QString("无法找到客户端连接: socket=%1").arg(socketDescriptor));
        }
        return;
    }

    infrastructure::io::TcpSocketClient* tcpClient = clients.value(socketDescriptor, nullptr);
    if (!tcpClient) {
        if (m_logger) {
            m_logger->error(QString("socket=%1 对应的TcpSocketClient为空").arg(socketDescriptor));
        }
        return;
    }

    // 为该连接创建协议解析器
    AutoDoorProtocol* protocol = new AutoDoorProtocol(m_logger, this);

    // 连接协议解析器的信号
    connect(protocol, &AutoDoorProtocol::helloReceived,
            this, &AutoDoorManager::onHelloReceived);
    connect(protocol, &AutoDoorProtocol::heartbeatReceived,
            this, &AutoDoorManager::onHeartbeatReceived);
    connect(protocol, &AutoDoorProtocol::ledAckReceived,
            this, &AutoDoorManager::onLedAckReceived);
    connect(protocol, &AutoDoorProtocol::ledErrorReceived,
            this, &AutoDoorManager::onLedErrorReceived);
    connect(protocol, &AutoDoorProtocol::protocolError,
            this, &AutoDoorManager::onProtocolError);

    // 连接TCP数据接收信号
    QMetaObject::Connection readConnection = connect(
        tcpClient,
        &infrastructure::io::TcpSocketClient::readyRead,
        this,
        [this, tcpClient, protocol]() {
        QByteArray data = tcpClient->readAll();
        protocol->appendData(data);

        // 尝试解析所有可用帧
        while (protocol->parseFrame()) {
            // 继续解析
        }
        });

    // 如果已有相同socket的待处理连接，先断开旧连接
    auto pendingIt = m_pendingDevices.find(socketDescriptor);
    if (pendingIt != m_pendingDevices.end()) {
        if (pendingIt->readConnection) {
            QObject::disconnect(pendingIt->readConnection);
        }
        if (pendingIt->protocol && pendingIt->protocol != protocol) {
            m_protocolToSocket.remove(pendingIt->protocol);
            pendingIt->protocol->deleteLater();
        }
        m_pendingDevices.erase(pendingIt);
    }

    // 临时存储（等待HELLO消息后才能确定deviceId）
    DeviceInfo tempDevice;
    tempDevice.socketDescriptor = socketDescriptor;
    tempDevice.tcpClient = tcpClient;
    tempDevice.protocol = protocol;
    tempDevice.readConnection = readConnection;
    tempDevice.state = DeviceState::Connecting;
    tempDevice.lastHeartbeat = QDateTime::currentDateTime();

    m_pendingDevices.insert(socketDescriptor, tempDevice);
    m_protocolToSocket.insert(protocol, socketDescriptor);

    if (m_logger) {
        m_logger->info(QString("自动门设备连接: IP=%1, Port=%2, Socket=%3")
            .arg(ip)
            .arg(port)
            .arg(socketDescriptor));
    }
}

void AutoDoorManager::onClientDisconnected(qint64 socketDescriptor, const QString& ip, quint16 port)
{
    // 先检查是否为未完成握手的临时连接
    auto pendingIt = m_pendingDevices.find(socketDescriptor);
    if (pendingIt != m_pendingDevices.end()) {
        if (m_logger) {
            m_logger->warning(QString("自动门设备握手前断开: Socket=%1, IP=%2, Port=%3")
                .arg(socketDescriptor)
                .arg(ip)
                .arg(port));
        }

        if (pendingIt->readConnection) {
            QObject::disconnect(pendingIt->readConnection);
        }
        if (pendingIt->protocol) {
            m_protocolToSocket.remove(pendingIt->protocol);
            pendingIt->protocol->deleteLater();
        }
        m_pendingDevices.erase(pendingIt);
        return;
    }

    // 查找断开的设备
    quint32 deviceId = m_socketToDevice.value(socketDescriptor, 0);

    if (deviceId != 0 && m_devices.contains(deviceId)) {
        DeviceInfo& device = m_devices[deviceId];

        if (m_logger) {
            m_logger->warning(QString("自动门设备断开: DeviceID=0x%1, IP=%2, Port=%3")
                .arg(deviceId, 8, 16, QChar('0'))
                .arg(ip)
                .arg(port));
        }

        // 删除协议解析器
        if (device.protocol) {
            device.protocol->deleteLater();
            device.protocol = nullptr;
        }
        if (device.readConnection) {
            QObject::disconnect(device.readConnection);
            device.readConnection = QMetaObject::Connection();
        }

        // 更新设备状态
        device.state = DeviceState::Offline;
        device.tcpClient = nullptr;

        emit deviceOffline(deviceId);

        // 从映射中移除
        m_socketToDevice.remove(socketDescriptor);
        m_devices.remove(deviceId);
    }
}

// ========== 协议消息处理（槽函数） ==========

void AutoDoorManager::onHelloReceived(quint32 deviceId, uint16_t fwVersion, uint8_t flags, uint16_t sequence)
{
    if (m_logger) {
        m_logger->info(QString("收到自动门设备HELLO: DeviceID=0x%1, FwVersion=0x%2, Flags=0x%3")
            .arg(deviceId, 8, 16, QChar('0'))
            .arg(fwVersion, 4, 16, QChar('0'))
            .arg(flags, 2, 16, QChar('0')));
    }

    // 查找发送者的协议对象
    AutoDoorProtocol* protocol = qobject_cast<AutoDoorProtocol*>(sender());
    if (!protocol) {
        return;
    }

    // 获取对应的临时连接信息
    qint64 socketDescriptor = m_protocolToSocket.value(protocol, -1);
    auto pendingIt = socketDescriptor != -1 ? m_pendingDevices.find(socketDescriptor) : m_pendingDevices.end();
    const bool hasPendingDevice = pendingIt != m_pendingDevices.end();
    DeviceInfo pendingDevice;
    if (hasPendingDevice) {
        pendingDevice = pendingIt.value();
        m_pendingDevices.erase(pendingIt);
    }
    if (socketDescriptor != -1) {
        m_protocolToSocket.remove(protocol);
    }

    auto deviceIt = m_devices.find(deviceId);
    const bool alreadyRegistered = deviceIt != m_devices.end();
    qint64 previousSocket = alreadyRegistered ? deviceIt.value().socketDescriptor : -1;

    if (!hasPendingDevice && !alreadyRegistered) {
        if (m_logger) {
            m_logger->error(QString("无法关联HELLO来源: DeviceID=0x%1").arg(deviceId, 8, 16, QChar('0')));
        }
        return;
    }

    DeviceInfo updatedDevice;
    if (hasPendingDevice) {
        updatedDevice = pendingDevice;
    } else {
        updatedDevice = deviceIt.value();
    }

    updatedDevice.deviceId = deviceId;
    updatedDevice.fwVersion = fwVersion;
    updatedDevice.flags = flags;
    updatedDevice.state = DeviceState::Online;
    updatedDevice.lastHeartbeat = QDateTime::currentDateTime();
    updatedDevice.protocol = protocol;

    if (alreadyRegistered) {
        DeviceInfo& currentDevice = deviceIt.value();
        if (hasPendingDevice) {
            if (currentDevice.readConnection) {
                QObject::disconnect(currentDevice.readConnection);
            }
            if (currentDevice.protocol && currentDevice.protocol != protocol) {
                currentDevice.protocol->deleteLater();
            }
        }
        currentDevice = updatedDevice;
    } else {
        deviceIt = m_devices.insert(deviceId, updatedDevice);
    }

    DeviceInfo& storedDevice = deviceIt.value();
    if (hasPendingDevice && previousSocket != -1 && previousSocket != storedDevice.socketDescriptor) {
        m_socketToDevice.remove(previousSocket);
    }
    if (storedDevice.socketDescriptor != -1) {
        m_socketToDevice.insert(storedDevice.socketDescriptor, deviceId);
    }

    QByteArray ackFrame = protocol->buildHelloAck(deviceId, 0, sequence);
    if (storedDevice.tcpClient) {
        qint64 bytesWritten = storedDevice.tcpClient->write(ackFrame);
        if (bytesWritten != ackFrame.size() && m_logger) {
            m_logger->warning(QString("发送HELLO_ACK失败: DeviceID=0x%1, 写入=%2, 期望=%3")
                .arg(deviceId, 8, 16, QChar('0'))
                .arg(bytesWritten)
                .arg(ackFrame.size()));
        }
    } else if (m_logger) {
        m_logger->error(QString("设备 0x%1 缺少有效的tcpClient，无法发送HELLO_ACK").arg(deviceId, 8, 16, QChar('0')));
    }

    if (alreadyRegistered) {
        if (m_logger) {
            m_logger->info(QString("设备 0x%1 重新连接").arg(deviceId, 8, 16, QChar('0')));
        }
    } else if (m_logger) {
        m_logger->info(QString("自动门设备注册: DeviceID=0x%1").arg(deviceId, 8, 16, QChar('0')));
    }

    emit deviceOnline(deviceId, fwVersion);
}

void AutoDoorManager::onHeartbeatReceived(quint32 deviceId, uint32_t uptime, uint16_t sequence)
{
    if (!m_devices.contains(deviceId)) {
        if (m_logger) {
            m_logger->warning(QString("收到未注册设备的心跳: DeviceID=0x%1").arg(deviceId, 8, 16, QChar('0')));
        }
        return;
    }

    DeviceInfo& device = m_devices[deviceId];
    device.lastHeartbeat = QDateTime::currentDateTime();

    // 发送 HEARTBEAT_ACK
    if (!device.protocol) {
        if (m_logger) {
            m_logger->error(QString("设备 0x%1 缺少protocol，无法发送HEARTBEAT_ACK").arg(deviceId, 8, 16, QChar('0')));
        }
        return;
    }

    QByteArray ackFrame = device.protocol->buildHeartbeatAck(deviceId, 0, sequence);
    if (device.tcpClient) {
        qint64 bytesWritten = device.tcpClient->write(ackFrame);
        if (bytesWritten != ackFrame.size() && m_logger) {
            m_logger->warning(QString("发送HEARTBEAT_ACK失败: DeviceID=0x%1, 写入=%2, 期望=%3")
                .arg(deviceId, 8, 16, QChar('0'))
                .arg(bytesWritten)
                .arg(ackFrame.size()));
        }
    } else if (m_logger) {
        m_logger->error(QString("设备 0x%1 缺少tcpClient，无法发送HEARTBEAT_ACK").arg(deviceId, 8, 16, QChar('0')));
    }
}

void AutoDoorManager::onLedAckReceived(uint32_t programId, uint8_t levelMask, uint16_t sequence)
{
    // 查找对应的门
    if (!m_programToDoor.contains(programId)) {
        if (m_logger) {
            m_logger->warning(QString("收到未知ProgramID的ACK: 0x%1").arg(programId, 8, 16, QChar('0')));
        }
        return;
    }

    int doorId = m_programToDoor[programId];
    m_programToDoor.remove(programId);

    if (m_logger) {
        m_logger->debug(QString("自动门控制成功: 门=%1, ProgramID=0x%2, LevelMask=0x%3")
            .arg(doorId)
            .arg(programId, 8, 16, QChar('0'))
            .arg(levelMask, 2, 16, QChar('0')));
    }

    // 更新门的状态
    auto door = getDoor(doorId);
    if (door) {
        // 根据levelMask判断是开还是关
        if (levelMask != 0) {
            door->open();
        } else {
            door->close();
        }
    }

    emit doorControlSuccess(doorId, levelMask);
}

void AutoDoorManager::onLedErrorReceived(uint32_t programId, LedErrorCode errorCode, uint16_t sequence)
{
    // 查找对应的门
    if (!m_programToDoor.contains(programId)) {
        if (m_logger) {
            m_logger->warning(QString("收到未知ProgramID的ERROR: 0x%1").arg(programId, 8, 16, QChar('0')));
        }
        return;
    }

    int doorId = m_programToDoor[programId];
    m_programToDoor.remove(programId);

    if (m_logger) {
        m_logger->error(QString("自动门控制失败: 门=%1, ProgramID=0x%2, ErrorCode=0x%3")
            .arg(doorId)
            .arg(programId, 8, 16, QChar('0'))
            .arg(static_cast<uint8_t>(errorCode), 2, 16, QChar('0')));
    }

    emit doorControlFailed(doorId, errorCode);
}

void AutoDoorManager::onProtocolError(const QString& error)
{
    if (m_logger) {
        m_logger->warning(QString("自动门协议错误: %1").arg(error));
    }
}

// ========== 定时任务 ==========

void AutoDoorManager::checkDeviceTimeout()
{
    QDateTime now = QDateTime::currentDateTime();

    for (auto it = m_devices.begin(); it != m_devices.end(); ) {
        DeviceInfo& device = it.value();

        if (device.state == DeviceState::Online) {
            qint64 secondsSinceLastHeartbeat = device.lastHeartbeat.secsTo(now);

            if (secondsSinceLastHeartbeat > HEARTBEAT_TIMEOUT) {
                if (m_logger) {
                    m_logger->warning(QString("自动门设备心跳超时: DeviceID=0x%1, 最后心跳=%2秒前")
                        .arg(device.deviceId, 8, 16, QChar('0'))
                        .arg(secondsSinceLastHeartbeat));
                }

                device.state = DeviceState::Offline;
                emit deviceOffline(device.deviceId);

                if (device.readConnection) {
                    QObject::disconnect(device.readConnection);
                    device.readConnection = QMetaObject::Connection();
                }
                if (device.socketDescriptor != -1) {
                    m_socketToDevice.remove(device.socketDescriptor);
                }
                if (device.protocol) {
                    device.protocol->deleteLater();
                    device.protocol = nullptr;
                }
                device.tcpClient = nullptr;

                // 移除设备
                it = m_devices.erase(it);
                continue;
            }
        }

        ++it;
    }
}

// ========== 内部辅助方法 ==========

bool AutoDoorManager::sendLedControl(quint32 deviceId, uint32_t programId, uint8_t levelMask)
{
    DeviceInfo* device = findDeviceById(deviceId);
    if (!device || device->state != DeviceState::Online) {
        if (m_logger) {
            m_logger->warning(QString("设备 0x%1 不在线，无法发送控制指令").arg(deviceId, 8, 16, QChar('0')));
        }
        return false;
    }

    if (!device->protocol || !device->tcpClient) {
        if (m_logger) {
            m_logger->error(QString("设备 0x%1 缺少protocol或tcpClient").arg(deviceId, 8, 16, QChar('0')));
        }
        return false;
    }

    // 构建LED_CONTROL帧
    QByteArray controlFrame = device->protocol->buildLedControl(programId, levelMask);

    // 发送
    qint64 bytesWritten = device->tcpClient->write(controlFrame);
    if (bytesWritten != controlFrame.size()) {
        if (m_logger) {
            m_logger->error(QString("发送LED控制指令失败: DeviceID=0x%1, 写入=%2, 期望=%3")
                .arg(deviceId, 8, 16, QChar('0'))
                .arg(bytesWritten)
                .arg(controlFrame.size()));
        }
        return false;
    }

    return true;
}

DeviceInfo* AutoDoorManager::findDeviceBySocket(qint64 socketDescriptor)
{
    quint32 deviceId = m_socketToDevice.value(socketDescriptor, 0);
    if (deviceId != 0 && m_devices.contains(deviceId)) {
        return &m_devices[deviceId];
    }
    return nullptr;
}

DeviceInfo* AutoDoorManager::findDeviceById(quint32 deviceId)
{
    if (m_devices.contains(deviceId)) {
        return &m_devices[deviceId];
    }
    return nullptr;
}

uint32_t AutoDoorManager::generateProgramId()
{
    return m_programIdCounter++;
}

void AutoDoorManager::startOrResetAutoCloseTimer(int doorId)
{
    QTimer* timer = m_autoCloseTimers.value(doorId, nullptr);
    if (!timer) {
        timer = new QTimer(this);
        timer->setSingleShot(true);
        connect(timer, &QTimer::timeout, this, [this, doorId]() {
            handleAutoCloseTimeout(doorId);
        });
        m_autoCloseTimers.insert(doorId, timer);
    }
    timer->start(AUTO_CLOSE_TIMEOUT_MS);
}

void AutoDoorManager::stopAutoCloseTimer(int doorId)
{
    if (QTimer* timer = m_autoCloseTimers.value(doorId, nullptr)) {
        timer->stop();
    }
}

void AutoDoorManager::handleAutoCloseTimeout(int doorId)
{
    auto configIt = m_doorConfigs.find(doorId);
    if (configIt == m_doorConfigs.end()) {
        if (QTimer* timer = m_autoCloseTimers.take(doorId)) {
            timer->stop();
            timer->deleteLater();
        }
        return;
    }

    const DoorConfig& config = configIt.value();
    auto door = config.doorObject;
    if (!door || door->isClosed()) {
        stopAutoCloseTimer(doorId);
        return;
    }

    if (!isDeviceOnline(config.deviceId)) {
        if (m_logger) {
            m_logger->warning(QString("自动门 %1 仍保持开启但设备 0x%2 离线，无法自动关门")
                .arg(doorId)
                .arg(config.deviceId, 8, 16, QChar('0')));
        }
        return;
    }

    if (m_logger) {
        m_logger->info(QString("自动门 %1 超时%2ms未收到新指令，执行自动关门")
            .arg(doorId)
            .arg(AUTO_CLOSE_TIMEOUT_MS));
    }

    closeDoor(doorId);
}

} // namespace auto_door
} // namespace application
